package com.kuangqi.paymentdemo.controller;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;

import com.kuangqi.paymentdemo.config.AlipayTemplate;

import com.kuangqi.paymentdemo.entity.OrderInfo;
import com.kuangqi.paymentdemo.entity.PayVo;

import com.kuangqi.paymentdemo.entity.QueryVo;
import com.kuangqi.paymentdemo.entity.RefundInfo;
import com.kuangqi.paymentdemo.enums.OrderStatus;
import com.kuangqi.paymentdemo.enums.wxpay.WxRefundStatus;

import com.kuangqi.paymentdemo.service.OrderInfoService;
import com.kuangqi.paymentdemo.service.RefundInfoService;
import com.kuangqi.paymentdemo.service.impl.CacheService;
import com.kuangqi.paymentdemo.vo.R;
import io.swagger.annotations.Api;

import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;


import java.util.*;

/**
 * @author kuanggong
 * @describe: 由于支付宝需要跳转链接, 故不用restcontroller
 */
@Slf4j
@Controller
@Api(tags = "支付宝网站支付")
@RequestMapping("/api/aliapy")
@CrossOrigin
public class AlipayController {

    @Autowired
    OrderInfoService orderInfoService;
    @Autowired
    AlipayTemplate alipayTemplate;
    @Autowired
    RefundInfoService refundInfoService;
    @Autowired
    CacheService cacheService;

    /**
     * 用户下单:支付宝支付
     * 1、让支付页让浏览器展示
     * 2、支付成功以后，跳转到用户的订单列表页
     *
     * @param orderSn
     * @return
     */
    @ApiOperation("下单")
    @ResponseBody
    @SneakyThrows
    @GetMapping(value = "/payorder", produces = "text/html")
    public String aliPayOrder(@RequestParam("orderno") String orderSn) {
        //TODO 实际开发当中 payVo的参数获取由前端传送
        PayVo payVo = new PayVo();
        payVo.setSubject("空调承太郎");
        payVo.setBody("空调承太郎");
        payVo.setTotal_amount("200");
        payVo.setOut_trade_no(orderSn);
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderNo(orderSn);
        orderInfo.setOrderStatus(OrderStatus.NOTPAY.getType());
        orderInfo.setTitle(payVo.getSubject());
        orderInfo.setTotalFee(Integer.parseInt(payVo.getTotal_amount()));
        orderInfoService.save(orderInfo);
        //ALIPAY 发送支付请求跳转并且根据return_url 回到商户支付完成页面
        String pay = alipayTemplate.pay(payVo);
        return pay;
    }

    @GetMapping(value = "/queryorder")
    @ResponseBody
    @SneakyThrows
    @ApiOperation("查单")
    public R aliPayQueryOrder(@RequestParam("orderno") String orderNo) {
        QueryVo queryVo = new QueryVo();

        OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper<OrderInfo>().eq("order_no", orderNo));
        queryVo.setOut_trade_no(orderNo);
        queryVo.setTrade_no(orderInfo.getOutTradeNo());
        String s = alipayTemplate.queryOrder(queryVo);
        //仅提供查询功能,修改订单具体状态需要具体实现。TRADE_SUCCESS

        JSONObject jsonObject = JSON.parseObject(s);


        Map<String, String> queryResponse = jsonObject.getObject("alipay_trade_query_response", Map.class);

        return R.ok().setMessage(queryResponse.get("trade_status").toString());
    }

    @GetMapping(value = "/refundorder")
    @ResponseBody
    @SneakyThrows
    @ApiOperation("退款发起")
    public R aliPayRefundOrder(@RequestParam("orderno") String orderNo) {
        try {
            OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper<OrderInfo>().eq("order_no", orderNo));
            if (orderInfo == null) {
                return R.error().setMessage("找不到订单,请检查核实");
            }

            RefundInfo info = refundInfoService.getOne(new QueryWrapper<RefundInfo>().eq("order_no", orderNo));
            if (info == null) {
                //未存在退款订单,执行退款请求
                RefundInfo refundInfo = new RefundInfo();
                double v = Double.parseDouble(orderInfo.getReceiptAmount());
                refundInfo.setRefund((int) v);
                refundInfo.setRefundNo(DateUtil.year(new Date()) + IdUtil.simpleUUID());
                refundInfo.setOrderNo(orderInfo.getOrderNo());
                refundInfo.setRefundStatus(WxRefundStatus.PROCESSING.getType());
                refundInfo.setTotalFee(orderInfo.getTotalFee());
                refundInfo.setReason("正常退款");
                refundInfo.setRefundId(orderInfo.getOutTradeNo());
                refundInfoService.save(refundInfo);


                orderInfoService.update(new UpdateWrapper<OrderInfo>().eq("order_no", orderNo).set("order_status", OrderStatus.REFUND_PROCESSING.getType()));
                Optional<String> responseData = alipayTemplate.refundOrder(refundInfo);
                // 对回退数据库进行修改

                String result = refundInfoService.updateRefundStatus(responseData, refundInfo);
                return R.ok().setMessage(result);
            } else {
                //已经存在该订单数据 判断订单状态
                if (info.getRefundStatus().equals(WxRefundStatus.PROCESSING.getType())) {
                    return R.ok().setMessage("不可重复发起退款请求");
                } else if (info.getRefundStatus().equals(WxRefundStatus.CLOSED.getType())) {
                    return R.ok().setMessage("订单已退款");
                } else {
                    return R.ok().setMessage("存在其他状态");
                }
            }
        } catch (Exception e) {
            log.error("程序出现异常[{}],", e);
            return R.error().setMessage("程序出现异常");
        }

    }

    //TODO 退款到银行卡 回调 ; 关闭交易;下载账单 ;接入花呗分期

    @GetMapping(value = "/closeorder")
    @ResponseBody
    @SneakyThrows
    @ApiOperation("关闭订单接口")
    public R aliPayCloseOrder(@RequestParam("orderno") String orderNo) {
        try {
            OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper<OrderInfo>().eq("order_no", orderNo));
            Optional<String> result = alipayTemplate.closeOrder(orderInfo);

            if (result.isPresent()) {
                orderInfo.setOrderStatus(OrderStatus.CANCEL.getType());
                orderInfoService.updateById(orderInfo);
                return R.ok().setMessage("用户已取消支付");

            } else {
                return R.error().setMessage("取消接口调用失败");
            }

        } catch (Exception e) {
            log.error("程序出现异常[{}],", e);
            return R.error().setMessage("程序出现异常");
        }

    }

    @GetMapping(value = "/downloadbill")
    @ResponseBody
    @SneakyThrows
    @ApiOperation("下载账单接口")
    public R aliPayBillQuery(@RequestParam("tradedate") String tradeDate) {
        try {

            Optional<String> result = alipayTemplate.queryBill(tradeDate);

            if (result.isPresent()) {
                //todo 下载账单
                alipayTemplate.downloadBill(result.get());

                return R.ok().setMessage("下载成功");

            } else {
                return R.error().setMessage("下载失败");
            }
        } catch (Exception e) {
            log.error("程序出现异常[{}],", e);
            return R.error().setMessage("程序出现异常");
        }

    }

}
